package due.pc.pcshoot.control;

import javax.microedition.khronos.opengles.GL10;

import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.engine.camera.hud.controls.BaseOnScreenControl;
import org.anddev.andengine.engine.handler.physics.PhysicsHandler;
import org.anddev.andengine.entity.IEntity;
import org.anddev.andengine.extension.input.touch.controller.MultiTouch;
import org.anddev.andengine.extension.input.touch.controller.MultiTouchController;
import org.anddev.andengine.extension.input.touch.exception.MultiTouchException;
import org.anddev.andengine.opengl.texture.Texture;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.region.TextureRegion;
import org.anddev.andengine.opengl.texture.region.TextureRegionFactory;
import org.anddev.andengine.util.MathUtils;

import android.content.Context;
import android.widget.Toast;

/**
 * 
 * @author manhhung.vu
 *
 */
public class OnScreenControl extends org.anddev.andengine.engine.camera.hud.controls.AnalogOnScreenControl
{

	//===============================================================/
	//Constants
	//===============================================================/
	public static final String CONTROLBASE_IMAGEPATH = "gfx/onscreen_control_base.png";
	public static final String CONTROLKNOB_IMAGEPATH = "gfx/onscreen_control_knob.png";
	
	public static final int CONTROL_WIDTH = 128;
	public static final int CONTROL_HEIGHT = 128;
	
	//===============================================================/
	//Fields
	//===============================================================/
	
	
	//===============================================================/
	//Constructors
	//===============================================================/
	private OnScreenControl(
			float pX, float pY, 
			Camera pCamera,
			TextureRegion pControlBaseTextureRegion,
			TextureRegion pControlKnobTextureRegion, 
			float pTimeBetweenUpdates,
			IAnalogOnScreenControlListener pAnalogOnScreenControlListener) 
	{
		super(pX, pY, pCamera, pControlBaseTextureRegion, pControlKnobTextureRegion,
				pTimeBetweenUpdates, pAnalogOnScreenControlListener);
	}
	
	
	//===============================================================/
	//Static Methods
	//===============================================================/
	/**
	 * Im Fall der Verwendung von 2 Controllern, muss diese Methode in Game::loadEngine
	 * aufgerufen werden.
	 * @param pEngine
	 */
	public static boolean registerMultitouchController(Engine pEngine, Context pContext)
	{
		boolean verticalDifference = false;
		try 
		{
			if(MultiTouch.isSupported(pContext)) 
			{
				//
				pEngine.setTouchController(new MultiTouchController());
				
				if(MultiTouch.isSupportedDistinct(pContext)) {
					Toast.makeText(pContext, "MultiTouch detected --> Both controls will work properly!", Toast.LENGTH_LONG).show();
				} else 
				{
					Toast.makeText(pContext, "MultiTouch detected, but your device has problems distinguishing between fingers.\n\nControls are placed at different vertical locations.", Toast.LENGTH_LONG).show();
					verticalDifference = true;
				}
			} 
			else Toast.makeText(pContext, "Sorry your device does NOT support MultiTouch!\n\n(Falling back to SingleTouch.)\n\nControls are placed at different vertical locations.", Toast.LENGTH_LONG).show();
		} 
		catch (final MultiTouchException e) {
			Toast.makeText(pContext, "Sorry your Android Version does NOT support MultiTouch!\n\n(Falling back to SingleTouch.)\n\nControls are placed at different vertical locations.", Toast.LENGTH_LONG).show();
		}
		
		return verticalDifference;
	}
	
	public static OnScreenControl createOnScreenControl(
			float pX, float pY, 
			Engine pEngine, Context pContext,
			IAnalogOnScreenControlListener pAnalogOnScreenControlListener)
	{
		Texture texture = new Texture(256, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		TextureRegion controlbaseTextureRegion = TextureRegionFactory.createFromAsset(
				texture, pContext, CONTROLBASE_IMAGEPATH, 0, 0);
		TextureRegion controlknobTextureRegion = TextureRegionFactory.createFromAsset(
				texture, pContext, CONTROLKNOB_IMAGEPATH, 128, 0);
		pEngine.getTextureManager().loadTexture(texture);
		
		OnScreenControl onScreenControl = new OnScreenControl(
				pX, pY, pEngine.getCamera(),
				controlbaseTextureRegion, controlknobTextureRegion, 
				0.1f, pAnalogOnScreenControlListener);
		
		onScreenControl.getControlBase().setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
		onScreenControl.getControlBase().setAlpha(0.5f);
		
		return onScreenControl;
	}
	
	public static IAnalogOnScreenControlListener newVelocityChangeOnScreenControlListener(PhysicsHandler pPhysicsHandler)
	{
		return new VelocityChangeOnScreenControlListener(pPhysicsHandler);
	}
	
	public static IAnalogOnScreenControlListener newRotationOnScreenControlListener(IEntity pEntity)
	{
		return new RotationOnScreenControlListener(pEntity);
	}
	
	//===============================================================/
	//Inner Classes
	//===============================================================/
	static class VelocityChangeOnScreenControlListener implements IAnalogOnScreenControlListener
	{
		PhysicsHandler mPhysicsHandler;
		
		public VelocityChangeOnScreenControlListener(PhysicsHandler pPhysicsHandler) {
			mPhysicsHandler = pPhysicsHandler;
		}

		@Override
		public void onControlClick(org.anddev.andengine.engine.camera.hud.controls.AnalogOnScreenControl pAnalogOnScreenControl) {}

		@Override
		public void onControlChange(BaseOnScreenControl pBaseOnScreenControl, float pValueX, float pValueY) {
			mPhysicsHandler.setVelocity(pValueX * 250, pValueY * 250);
		}
	}
	
	static class RotationOnScreenControlListener implements IAnalogOnScreenControlListener
	{
		IEntity mEntity;
		public RotationOnScreenControlListener(IEntity pEntity) {
			mEntity = pEntity;
		}
		
		@Override
		public void onControlClick(org.anddev.andengine.engine.camera.hud.controls.AnalogOnScreenControl pAnalogOnScreenControl) {}
		
		@Override
		public void onControlChange(BaseOnScreenControl pBaseOnScreenControl, float pValueX, float pValueY) {
			if(pValueX == 0 && pValueY == 0) {
				mEntity.setRotation(0);
			} else {
				mEntity.setRotation(MathUtils.radToDeg((float)Math.atan2(pValueX, -pValueY)));
			}
		}
	}
}
